home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / BlobMgr / Demo Folder / Pong.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  7.6 KB  |  376 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Blob Manager Demonstration:  Pong hau k'i module
  3.  *
  4.  * This is an oriental game played on a 5-position board.  Each player
  5.  * has 2 pieces, and the goal is to position to pieces so that the
  6.  * other player cannot move.  Pieces may be moved onto the empty
  7.  * position only if the two are connected by a line.
  8.  *
  9.  * *     *
  10.  * |\  / |
  11.  * |  *  |
  12.  * |/  \ |
  13.  * *-----*
  14.  *
  15.  * Since it's so simple, the game gives no feedback.  You simply
  16.  * cannot move if the game is over.  The reset "button" can be
  17.  * used to start over when the game has been completed.
  18.  *
  19.  * 5 August 1986        Paul DuBois
  20.  */
  21.  
  22. # include    "TransSkel.h"
  23.  
  24. # include    "BlobMgr.h"
  25. # include    "BlobDemo.h"
  26.  
  27.  
  28. # define    pieceSize    20        /* size of each piece */
  29. # define    hOff        15        /* top left corner of playing area */
  30. # define    vOff        20
  31. # define    hSize        80        /* size of playing area */
  32. # define    vSize        60
  33. # define    vMesg        100
  34.  
  35.  
  36. static WindowPtr        wind;
  37.  
  38. static BlobSetHandle    boardBlobs = nil;
  39. static BlobHandle        board[5];
  40. static BlobSetHandle    donors = nil;
  41. static BlobHandle        current;
  42. static BlobHandle        previous;
  43. static BlobSetHandle    misc;
  44. static BlobHandle        resetBlob;    /* simulated control */
  45. static Str255            statusStr;
  46. static BlobHandle        statusBlob;
  47.  
  48.  
  49. /*
  50.  * Define center points of each position
  51.  */
  52.  
  53. static Point            intersection[5] =
  54. {
  55.     { vOff, hOff },
  56.     { vOff, hOff + hSize },
  57.     { vOff + vSize/2, hOff + hSize/2 },
  58.     { vOff + vSize, hOff },
  59.     { vOff + vSize, hOff + hSize }
  60. };
  61.  
  62. /*
  63.  * Define connections between positions
  64.  */
  65.  
  66. static Boolean            connected[5][5] =
  67. {
  68.     { false,    false,    true,    true,    false },
  69.     { false,    false,    true,    false,    true },
  70.     { true,        true,    false,    true,    true },
  71.     { true,        false,    true,    false,    true },
  72.     { false,    true,    true,    true,    false } 
  73. };
  74.     
  75.  
  76. static void
  77. StatusMesg (StringPtr s, BlobHandle b)
  78. {
  79. Rect    r;
  80.  
  81.     SetRect (&r, 0, vMesg, 55, vMesg + 20);
  82.     TextBox (s+1, (long) s[0], &r, teJustRight);
  83.     GlueGlob (b, GetBlobHandle (misc, 0));
  84.     StrCpy (statusStr, s);
  85.     statusBlob = b;
  86. }
  87.  
  88.  
  89. /*
  90.  * The donor set consists of two blobs, each filled with a different
  91.  * pattern
  92.  */
  93.  
  94. static void
  95. MakeDonors (void)
  96. {
  97. BlobHandle    b;
  98. Rect        r;
  99. RgnHandle    rgn;
  100. Pattern        p;
  101. short        i;
  102.  
  103.     donors = NewBlobSet ();
  104.     for (i = 9; i <= 16; i += 7)    /* use patterns 9, 16 */
  105.     {
  106.         rgn = NewRgn ();
  107.         OpenRgn ();
  108.         SetRect (&r, 0, 0, pieceSize, pieceSize);
  109.         FrameOval (&r);
  110.         CloseRgn (rgn);
  111.  
  112.         b = NewBlob (donors, true, infiniteGlue, false, 0L);
  113.         OpenBlob ();
  114.         GetIndPattern (p, sysPatListID, i);
  115.         FillOval (&r, p);
  116.         FrameOval (&r);
  117.         CloseRgnBlob (b, rgn, rgn);
  118.         DisposeRgn (rgn);
  119.     }
  120. }
  121.  
  122.  
  123. static BlobHandle
  124. MakeReceptor (BlobSetHandle bSet, short h, short v)
  125. {
  126. BlobHandle    b;
  127. Rect        r;
  128. RgnHandle    rgn;
  129.  
  130.     SetRect (&r, h, v, h + pieceSize, v + pieceSize);
  131.     rgn = NewRgn ();
  132.     OpenRgn ();
  133.     FrameOval (&r);
  134.     CloseRgn (rgn);
  135.  
  136.     b = NewBlob (bSet, true, 0, false, 0L);
  137.     OpenBlob ();
  138.     EraseOval (&r);
  139.     FrameOval (&r);
  140.     CloseRgnBlob (b, rgn, rgn);
  141.     DisposeRgn (rgn);
  142.     return (b);
  143. }
  144.  
  145.  
  146. static void
  147. MakeBoard (void)
  148. {
  149. short        i;
  150. Rect        r;
  151.  
  152.     boardBlobs = NewBlobSet ();
  153.     for (i = 0; i < 5; i++)
  154.     {
  155.         board[i] = MakeReceptor (boardBlobs,
  156.                                     intersection[i].h - pieceSize/2,
  157.                                     intersection[i].v - pieceSize/2);
  158.     }
  159.  
  160.     misc = NewBlobSet ();
  161.     (void) MakeReceptor (misc, 60, vMesg - 2);
  162.     SetRect (&r, 0, 0, 20, 90);
  163.     OffsetRect (&r, wind->portRect.right - 25, 5);
  164.     resetBlob = NewVButtonBlob (misc, &r, "\pReset", true);
  165. }
  166.  
  167.  
  168. /*
  169.  * Set the board to the initial configuration
  170.  */
  171.  
  172. static void
  173. Reset (void)
  174. {
  175. short    i;
  176.  
  177.     UnglueGlobSet (boardBlobs);        /* clear all globs */
  178.     GlueGlob (GetBlobHandle (donors, 0), board[0]);
  179.     GlueGlob (GetBlobHandle (donors, 0), board[1]);
  180.     GlueGlob (GetBlobHandle (donors, 1), board[3]);
  181.     GlueGlob (GetBlobHandle (donors, 1), board[4]);
  182.     current = FirstBlob (donors);
  183.     previous = NextBlob (current);
  184.     StatusMesg ("\pMove:", current);
  185.     HiliteBlob (resetBlob, inDragBlob, dimDraw);
  186. }
  187.  
  188.  
  189. /*
  190.  * Given a blob handle, find the board position that corresponds to it.
  191.  */
  192.  
  193. static short
  194. BoardPos (BlobHandle b)
  195. {
  196. short    i;
  197.  
  198.     for (i = 0; i < 5; ++i)
  199.     {
  200.         if (board[i] == b)
  201.             return (i);
  202.     }
  203.     /* shouldn't ever get here */
  204. }
  205.  
  206.  
  207. /*
  208.  * Test whether a piece can move or not.  This is true only if
  209.  * the current position is connected to the empty position (of which
  210.  * there is only one).
  211.  */
  212.  
  213. static Boolean
  214. CanMove (short n)
  215. {
  216. short    i;
  217.  
  218.     for (i = 0; i < 5; ++i)
  219.     {
  220.         if (i != n && connected [i][n] && BGlob (board[i]) == nil)
  221.             return (true);
  222.     }
  223.     return (false);
  224. }
  225.  
  226.  
  227. /*
  228.  * See whether the game is over or not.  It's over if no piece 
  229.  * of the current player can move.
  230.  */
  231.  
  232. static Boolean
  233. GameOver (void)
  234. {
  235. short        i;
  236.  
  237.     for (i = 0; i < 5; ++i)
  238.     {
  239.         if (BGlob (board[i]) == current && CanMove (i))
  240.             return (false);
  241.     }
  242.     return (true);
  243. }
  244.  
  245.  
  246. /*
  247.  * When a piece is clicked on, the advisory checks whether the piece
  248.  * belongs to the correct player and whether the piece has
  249.  * any legal moves available to it.  If so, it returns true, so that
  250.  * BlobClick is allowed to drag the piece.  After the piece has been
  251.  * dragged, the advisory checks whether the position it was dragged to
  252.  * is legal (connected to original position), and returns true if so.
  253.  *
  254.  * Messages passed to the advisory follow the pattern
  255.  *
  256.  * { { advRClick advRClick* } advXfer* }*
  257.  *
  258.  * where * means 0 or more instances of the thing *'ed.  In particular,
  259.  * the advXfer message is never seen without a preceding advRClick.
  260.  */
  261.  
  262. static pascal Boolean
  263. Advisory (short mesg, BlobHandle b)
  264. {
  265. static short    n;        /* static to save board position of click on piece */
  266.  
  267.     switch (mesg)
  268.     {
  269.  
  270.     case advRClick:    /* first click on piece */
  271.  
  272.         if (BGlob (b) != current)
  273.             return (false);            /* can only move current piece(s) */
  274.         n = BoardPos (b);            /* find where it is */
  275.         return (CanMove (n));
  276.  
  277.     case advXfer:    /* Mouse released after dragging piece */
  278.  
  279.         return (connected [n][BoardPos (b)]);
  280.     }
  281. }
  282.  
  283.  
  284.  
  285. static pascal void
  286. Mouse (Point pt, long t, short mods)
  287. {
  288. BlobHandle    b;
  289. short        i;
  290.  
  291.     if (TestBlob (resetBlob, pt) == inDragBlob)
  292.     {
  293.         if (BTrackMouse (resetBlob, pt, inFullBlob))
  294.             Reset ();
  295.     }
  296.     else
  297.     {
  298.         BlobClick (pt, t, nil, boardBlobs);
  299.         if (BClickResult () == bcXfer)
  300.         {
  301.             b = current;                /* switch player */
  302.             current = previous;
  303.             previous = b;
  304.             if (GameOver ())            /* see if board is locked */
  305.             {
  306.                 StatusMesg ("\pWins:", previous);
  307.                 HiliteBlob (resetBlob, inDragBlob, normalDraw);
  308.             }
  309.             else
  310.                 StatusMesg ("\pMove:", current);
  311.         }
  312.     }
  313. }
  314.  
  315.  
  316. static pascal void
  317. Update (Boolean resized)
  318. {
  319.     MoveTo (intersection[3].h, intersection[3].v);    /* draw board */
  320.     LineTo (intersection[0].h, intersection[0].v);
  321.     LineTo (intersection[4].h, intersection[4].v);
  322.     LineTo (intersection[1].h, intersection[1].v);
  323.     LineTo (intersection[3].h, intersection[3].v);
  324.     LineTo (intersection[4].h, intersection[4].v);
  325.     DrawBlobSet (boardBlobs);
  326.     DrawBlobSet (misc);
  327.     StatusMesg (statusStr, statusBlob);
  328. }
  329.  
  330.  
  331. /*
  332.  * Activate the window:  Set the advisory function and set the permissions
  333.  * to transfer-only.  Clear, replace, duplication and swap are off.
  334.  * Since replace is off, the advisory doesn't have to check whether
  335.  * the dragged piece was dragged onto a blob that already has a glob.
  336.  *
  337.  * Deactivate the window:  Clear the advisory.
  338.  */
  339.  
  340. static pascal void
  341. Activate (Boolean active)
  342. {
  343.  
  344.     if (active)
  345.     {
  346.         SetDragRects (wind);
  347.         SetBCPermissions (false, true, false, false, false);    /* xfer only */
  348.         SetBCAdvisory (Advisory);
  349.     }
  350.     else
  351.     {
  352.         SetBCAdvisory (nil);
  353.     }
  354. }
  355.  
  356.  
  357. void
  358. PongInit (void)
  359. {
  360.     SkelWindow (wind = GetDemoWind (pongWindRes),
  361.                 Mouse,            /* mouse clicks */
  362.                 nil,            /* key clicks */
  363.                 Update,            /* updates */
  364.                 Activate,        /* activate/deactivate events */
  365.                 nil,            /* close window */
  366.                 DoWClobber,        /* dispose of window */
  367.                 nil,            /* idle proc */
  368.                 false);            /* irrelevant, since no idle proc */
  369.  
  370.     MakeDonors ();
  371.     MakeBoard ();
  372.     Reset ();
  373.  
  374.     MakeFrontWind (wind);
  375. }
  376.